home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource4
/
228_01
/
bdsmark.c
< prev
next >
Wrap
Text File
|
1987-07-31
|
6KB
|
233 lines
/*
** bdsmark.c -- mark library functions that BDS C implements in a
** nonstandard fashion.
**
** This program will accept a BDS C program as input and write
** the program to its output with markers placed around the BDS C
** standard library functions that are not implemented in a standard
** manner. In some cases the differences are trivial. Other times
** they are not. Using this program to mark a file can help in
** converting a file to portable form for compilation in a system
** with a standard "standard" library.
**
** David D. Clark
** 3 February 1987
*/
#include "stdio.h" /* Aztec won't take "<...>" notation */
/*#include "ctype.h"*/ /* delete for 8 bit versions */
#define QC
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define TOKLEN 9 /* max length for token to test */
#define MARKER "^^" /* marker in output file */
char *nonstd[] = /* nonstandard functions */
{ /* reason: */
"creat", /* parameters */
"exit", /* doesn't flush files */
"fgets", /* parameters */
"fopen", /* parameters */
"getc", /* text vs binary i/o */
"getchar", /* text vs binary i/o */
"putc", /* text vs binary i/o */
"puts", /* doesn't append '\n' */
"read", /* parameters */
"tolower", /* checks argument range */
"toupper", /* checks argument range */
"write" /* parameters */
};
char c; /* current scanner character */
char token[TOKLEN]; /* token to be tested */
FILE *infile, *outfile; /* input and output files */
FILE *fopen();
main(argc, argv)
int argc;
char *argv[];
{
if (argc != 3)
{
fputs("Usage: bdsmark infile outfile\n", stderr);
exit(1);
}
if ((infile = fopen(*++argv, "r")) == NULL)
{
fputs("Can't open input file: ", stderr);
fputs(*argv, stderr);
putc('\n', stderr);
exit(1);
}
if ((outfile = fopen(*++argv, "w")) == NULL)
{
fputs("Can't open output file: ", stderr);
fputs(*argv, stderr);
putc('\n', stderr);
exit(1);
}
scanner(); /* do the translation */
fclose(infile);
fclose(outfile);
exit(0);
}
/*
** scanner -- scan the input file and produce the marked
** output file. This function looks specifically for comments,
** string constants, character constants and identifiers. When
** a potential comment is detected, control is passed to the
** function "commenter" to pass the rest of the comment without
** change. String and character constants are also passed unchanged.
** When an identifier is detected, it is copied into the global
** character array "token", then "tsttoken" is called to compare
** it to the names of the nonstandard functions. If a match is
** found, it is marked in the output file.
*/
scanner()
{
static char *cp;
static int i;
while ((c = getc(infile)) && !feof(infile) && !ferror(infile))
{
if (c == '/') /* check for a comment */
commenter();
else if (c == '\'') /* handle character constant */
passuntil('\'');
else if (c == '"') /* handle literal string */
passuntil('"');
else if (iscsymf(c)) /* look for an identifier */
{
i = 0;
cp = token;
while (iscsym(c) && (i < (TOKLEN - 1)))
{
*cp++ = c;
i++;
c = getc(infile);
}
*cp = 0;
if (tsttoken()) /* mark it */
{
fputs(MARKER, outfile);
fputs(token, outfile);
fputs(MARKER, outfile);
}
else
fputs(token, outfile);
}
putc(c, outfile); /* write last char scanned */
}
putc(c, outfile); /* try to write end-of-file char */
}
/*
** passuntil -- pass characters from "infile" to "outfile" until
** the terminator character "term" is detected. Detect and pass
** "escaped" character sequences unchanged. On entry, the scanner
** character in "c" has not yet been written to the output file. On
** return, the scanner character will contain the terminator character
** ready for output.
*/
passuntil(term)
int term;
{
putc(c, outfile);
while ((c = getc(infile)) != term)
{
putc(c, outfile);
if (c == '\\')
{
c = getc(infile);
putc(c, outfile);
}
}
}
/*
** tsttoken -- return TRUE if the token matches one of the
** names of the nonstandard functions in the variable "nonstd", FALSE
** otherwise. Because there are only a few, a simple linear search
** is done on the array.
*/
int tsttoken()
{
static char **t;
for (t = nonstd; **t; t++)
{
if (strcmp(*t, token) == 0)
return (TRUE);
}
return (FALSE);
}
/*
** commenter -- pass comments unchanged. On entry, the leading
** '/' has already been detected. On return, c contains the final '/'
** of the comment.
**
** This function expects comments to be in the UNIX style. It
** does not handle nested comments correctly. In any case, the
** damage caused by nested comments should be minimal. The worst
** that should occur is marking of nonstandard function names that
** appear in the comment.
*/
commenter()
{
putc(c, outfile); /* write the '/' char */
if ((c = getc(infile)) == '*') /* is next char '*'? */
{ /* yes, handle rest of comment */
putc(c, outfile);
c = getc(infile);
for (;;)
{
putc(c, outfile);
if (c == '*') /* '*' of end of comment? */
{
if ((c = getc(infile)) == '/')
return; /* got it all */
else
putc(c, outfile);
}
c = getc(infile);
}
}
}
#ifndef QC
/*
** iscsymf -- is c a valid character for the first character in
** a C symbol?
*/
int iscsymf(c)
int c;
{
return (isalpha(c) || c == '_');
}